1_approximation.f90 Source File


Source Code

module approximation
    !! polinomial approximation
    use kind_module    
    implicit none
    
contains

real(wp) function polin(k,x)
    implicit none
    integer k
    real(wp) x
    polin=1d0
    if(k.gt.1) polin=x**(k-1)
    return
end

real(wp) function polin1(k,x)
    implicit none
    integer k
    real(wp) x
    polin1=x**k
    return
end

real(wp) function polin2(k,x)
    implicit none
    integer k
    real(wp) x
    polin2=x**(k+1)
    return
end

subroutine approx(x,y,n,f,m,b)
!!     \(y(i)=y(x(i))\)  the data to be approximated.  
!!     \(n\)  number of points in the input data.  
!!     \(m\)  number of coefficients of decomposition
!!            over base functions \(f(k,x)\) :  
!!     \(y(x)=sum_1^m [b(k)*f(k,x)]\)  
!!     \(b(i)\)  found decomposition coefficients 

    implicit real*8 (a-h,o-z)
    integer,  parameter :: np=20
    real(wp), parameter :: zero=0.d0
    real(wp) a(np,np),indx(np)
    real(wp) y(n),x(n),b(*)
    integer i,j,k,m,n
    if(m.gt.np) then
        write(*,*)'index error subroutine "approx"'
        return
    end if

    do j=1,m
        do k=1,j
            a(k,j)=zero
            do i=1,n
                a(k,j)=a(k,j)+f(j,x(i))*f(k,x(i))
            end do
        end do
    end do
    do k=2,m
        do j=1,k-1
            a(k,j)=a(j,k)
        end do
    end do

    do k=1,m
     b(k)=zero
      do i=1,n
       b(k)=b(k)+y(i)*f(k,x(i))
      end do
    end do

    call ludcmp(a,m,np,indx,d)
    call lubksb(a,m,np,indx,b)
end

subroutine ludcmp(a,n,np,indx,d)
    implicit real*8 (a-h,o-z)
    integer,  parameter :: nmax=501
    real(wp), parameter :: tiny=1.d-20, zero=0.d0
    real(wp) a(np,np),indx(n),vv(nmax)
    integer i,j,k,m,n,np,imax
    d=1.d0
    do i=1,n
        aamax=zero
        do j=1,n
            if (dabs(a(i,j)).gt.aamax) aamax=dabs(a(i,j))
        end do
        if (aamax.eq.zero) pause 'singular matrix.'
            vv(i)=1.d0/aamax
    end do
    do j=1,n
    if (j.gt.1) then
    do i=1,j-1
      sum=a(i,j)
      if (i.gt.1)then
        do k=1,i-1
          sum=sum-a(i,k)*a(k,j)
        end do
        a(i,j)=sum
      endif
    end do
    endif
    aamax=zero
    do i=j,n
        sum=a(i,j)
        if (j.gt.1)then
            do k=1,j-1
                sum=sum-a(i,k)*a(k,j)
            end do
        a(i,j)=sum
        endif
        dum=vv(i)*dabs(sum)
        if (dum.ge.aamax) then
            imax=i
            aamax=dum
        endif
    end do
    if (j.ne.imax) then
        do k=1,n
            dum=a(imax,k)
            a(imax,k)=a(j,k)
            a(j,k)=dum
        end do
        d=-d
        vv(imax)=vv(j)
    endif
    indx(j)=imax
    if (j.ne.n) then
        if (a(j,j).eq.zero) a(j,j)=tiny
        dum=1.d0/a(j,j)
        do i=j+1,n
            a(i,j)=a(i,j)*dum
        end do
    endif
    end do
    if(a(n,n).eq.zero) a(n,n)=tiny
    return
end

subroutine lubksb(a,n,np,indx,b)
    implicit real*8 (a-h,o-z)
    real(wp), parameter :: zero=0.d0
    real(wp)  a(np,np),indx(n),b(n)
    integer i,j,ii,ll,n,np 
    ii=0
    do i=1,n
        ll=indx(i)
        sum=b(ll)
        b(ll)=b(i)
        if (ii.ne.0)then
            do j=ii,i-1
                sum=sum-a(i,j)*b(j)
            end do
        else if (sum.ne.zero) then
            ii=i
        endif
        b(i)=sum
    end do
    do i=n,1,-1
        sum=b(i)
        if(i.lt.n)then
            do j=i+1,n
                sum=sum-a(i,j)*b(j)
            end do
        endif
        b(i)=sum/a(i,i)
    end do
    return
end    

    function fdf(x, c, n, df) result(p)
        !! вычисление значения полинома и его производной
        real(wp), intent(in)  :: x
        real(wp), intent(in)  :: c(n)
        integer,  intent(in)  :: n
        real(wp), intent(out) :: df
        integer               :: j
        real(wp)              :: p, dp
        p=c(n)
        dp=0.d0
        do j=n-1,1,-1
            dp=dp*x+p
            p=p*x+c(j)
        end do
        df=dp
    end

real(wp) function fdfddf(x,c,n,df,ddf)
    !! вычисление значения полинома и первой и второй производной
    real(wp), intent(in)   :: x
    real(wp), intent(in)   :: c(n)
    integer,  intent(in)   :: n 
    real(wp), intent(out)  :: df
    real(wp), intent(out)  :: ddf
    integer j
    real(wp) p, dp,ddp
    p=c(n)
    dp=0d0
    ddp=0d0
    do j=n-1,1,-1
        ddp=ddp*x+2d0*dp
        dp=dp*x+p
        p=p*x+c(j)
    end do
    fdfddf=p
    df=dp
    ddf=ddp
end


end module approximation